package _2_01_interface

import "fmt"
// -------------定义接口-------------
type Phone interface {
	call()
}

// 定义iphone实现
type IPhone struct {

}
// 使用值接收参数
func (iphone IPhone) call() {
	fmt.Println("iphone impl call...")
}
func (iphone IPhone) play()  {
	fmt.Println("iphone impl play...")
}

// 定义小米phone实现
type XiaoMi struct {

}
func (xiaomi XiaoMi) call()  {
	fmt.Println("xiaomi call...")
}

func PhoneCall() {
	var phone Phone     // 声明一个Phone类型的变量phone
	phone = new(IPhone) // 实例化IPhone赋值给phone
	phone.call()        // 使用phone调用call方法，实际调用的是存储在phone变量里面的IPhone实例所实现的call方法
	phone = new(XiaoMi) // 实例化XiaoMi赋值给phone
	phone.call()

}
// -----------------值接受者----------------------
func valueConsumer() {
	var phone Phone
	iphone1 := IPhone{}
	phone = iphone1		 			// 直接将值类型赋值给phone
	phone.call()
	iphone2 := &IPhone{}
	phone = iphone2					// 将指针类型&Phone赋值给phone, 会自动根据指针求值*iphone2，然后将其赋值给变量phone
	phone.call()

}

// 使用指针接受者实现接口
func (iphone *IPhone) pointCall() {
	fmt.Println("iphone call...")
}
// ---------------指针接收参数---------------------
func pointConsumer() {

	var phone Phone
	iphone1 := IPhone{}
	phone = iphone1		 			// 直接将值类型赋值给phone，报错
	phone.call()
	iphone2 := &IPhone{}
	phone = iphone2					// 将指针类型&Phone赋值给phone
	phone.call()

}

// -----------------------实现多个接口------------------------
type Game interface {
	play()
}

type Refrigerator struct {
	
}
type Elephant struct {
	
}
// 定义一个接口中多个方法
type PutElephantIntoRefrigerator interface {
	OpenTheDoorOfRefrigerator(Refrigerator) error
	PutTheDoorOfRefrigerator(Elephant, Refrigerator) error
}
type TestTypeImplInterface func()

func (t TestTypeImplInterface) OpenTheDoorOfRefrigerator(Refrigerator) error  {
	return nil
}
func (t TestTypeImplInterface)PutTheDoorOfRefrigerator(Elephant, Refrigerator) error {
	return nil
}
// 必须实现所有的接口方法，才叫做实现接口，且不限类型，否则不算实现
type PutElephantIntoRefrigeratorImpl struct {

}
func (t PutElephantIntoRefrigeratorImpl) OpenTheDoorOfRefrigerator(Refrigerator) error  {
	return nil
}
func (t *PutElephantIntoRefrigeratorImpl)PutTheDoorOfRefrigerator(Elephant, Refrigerator) error {
	return nil
}
func PutElephantIntoRefrigeratorMain() {
	refrigerator := Refrigerator{}
	elephant := Elephant{}
	var putEr PutElephantIntoRefrigerator = &PutElephantIntoRefrigeratorImpl{} // 其中一个成员方法是指针类型，必须使用指针类型
	putEr.PutTheDoorOfRefrigerator(elephant, refrigerator)
	putEr.OpenTheDoorOfRefrigerator(refrigerator)
}


// -----------------------封装------------------------
type student struct {
	Name string

	Age int

	Gender string

	Grade string
}
func GetAge(student2 *student) int {
	return student2.Age
}

// -----------------------继承------------------------
type Animal struct {
	Age int
	Weight float32
}
// animal方法
func (an *Animal) Show()  {
	fmt.Println("Show call...")
}
func (an *Animal) ShowInfo()  {
	fmt.Println("Show call...age:%v,weight:%v", an.Age, an.Weight)
}
func (an *Cat) ShowInfo()  {
	fmt.Println("Show call...age:%v,weight:%v", an.Age, an.Weight)
}
//cat特有方法
type Cat struct {
	// 加入匿名结构体
	Animal

}
type AnimalCat struct {
	Animal
	Cat
	int
}

func (c *Cat) scratch() {
	fmt.Println("Cat的特有方法 call...",)
}


type A struct {
	Age int
	Weight float32
}
type B struct {
	Age int
	Weight float32
}
type C struct {
	A
	B
	int
}
func mainCall()  {
	cat := &Cat{}
	cat.Animal.Age=3
	cat.Animal.Weight=10.8
    cat.Animal.Show()
	cat.scratch() // 调用猫特有方法

	cat.Age=3
	cat.Weight=10.8
	cat.Show()
	cat.ShowInfo() // 访问的是cat 的
	cat.Animal.ShowInfo()// 访问的是animal 的

	ac := C{A{1,2}, B{2,3}, 3}
	fmt.Println(ac)
}

// ****************************************************
type downloadFromDisk struct {
	secret   DynamicSecret // 结构体中定义接口类型
	filePath string
}
type DynamicSecret interface {
	GetSecret() string
}
type mobileTokenDynamic struct {
	moileNumber string
}

func (d *mobileTokenDynamic)GetSecret() string {
	return "something"
}

func (dd *downloadFromDisk) DownloadFile() {
	err := dd.logincheck()
	if err != nil {
		return
	}
	dd.downloadFromAliYun(dd.filePath)
}
func (dd *downloadFromDisk) logincheck() error {
	dd.checkSecret(dd.secret.GetSecret())
	return nil
}
func (dd *downloadFromDisk) downloadFromAliYun(file string) error {

	return nil
}
func (dd *downloadFromDisk) checkSecret(secret string) error {
	return nil
}

type Door interface {
	UnLock()
	Open()
	Close()
	Lock()
}
type GlassDoor struct {

}

var _ Door = &GlassDoor{} // 这个定义就是强制要求Door的实现，必须实现Door的所有方法

func (g GlassDoor) UnLock() {
	panic("implement me")
}

func (g GlassDoor) Open() {
	panic("implement me")
}

func (g GlassDoor) Close() {
	panic("implement me")
}

func (g GlassDoor) Lock() {
	panic("implement me")
}
